<?php
/***********************************************************************
 * @package     IvanEngine
 * @subpackage  Core
 * @author      Ivan <ivanzx@msn.com>
 * @created     2010-07-17
 * @Purpose     
 ***********************************************************************/
if(defined("IVANENGINE_CORE_ASSETMHELPER"))
    die("Redefinition macro in :".__FILE__."(".__LINE__.")");
define("IVANENGINE_CORE_ASSETMHELPER", true);

require_once (dirname(__FILE__).'/../Common.php');

class CAssetHelper extends CBase
{
    public function __construct()
    {
        parent::__construct();
    }
    
    public function __destruct()
    {
        parent::__destruct();
    }
    
    static public function AutoDiscoveryLinkTag($type = 'rss', $url = '', $tag_options = array())
    {
        return CTagHelper::Tag('link', array(
        'rel'   => isset($tag_options['rel']) ? $tag_options['rel'] : 'alternate',
        'type'  => isset($tag_options['type']) ? $tag_options['type'] : 'application/'.$type.'+xml',
        'title' => isset($tag_options['title']) ? $tag_options['title'] : ucfirst($type),
        'href'  => CUrlHelper::UrlFor($url, true)
        ));
    }

    /**
    * Returns the path to a JavaScript asset.
    *
    * <b>Example:</b>
    * <code>
    *  echo self::JavascriptPath('myscript');
    *    => /js/myscript.js
    * </code>
    *
    * <b>Note:</b> The asset name can be supplied as a...
    * - full path, like "/my_js/myscript.css"
    * - file name, like "myscript.js", that gets expanded to "/js/myscript.js"
    * - file name without extension, like "myscript", that gets expanded to "/js/myscript.js"
    *
    * @param string $source   asset name
    * @param bool   $absolute return absolute path ?
    *
    * @return string file path to the JavaScript file
    * @see    self::JavascriptIncludeTag
    */
    static public function JavascriptPath($source, $absolute = false)
    {
        return self::_ComputePublicPath($source, 'js', 'js', $absolute);
    }

    /**
    * Returns a <script> include CTagHelper::CTagHelper::Tag per source given as argument.
    *
    * <b>Examples:</b>
    * <code>
    *  echo self::JavascriptIncludeTag('xmlhr');
    *    => <script language="JavaScript" type="text/javascript" src="/js/xmlhr.js"></script>
    *  echo self::JavascriptIncludeTag('common.javascript', '/elsewhere/cools');
    *    => <script language="JavaScript" type="text/javascript" src="/js/common.javascript"></script>
    *       <script language="JavaScript" type="text/javascript" src="/elsewhere/cools.js"></script>
    * </code>
    *
    * @param string asset names
    * @param array additional HTML compliant <link> CTagHelper::CTagHelper::Tag parameters
    *
    * @return string XHTML compliant <script> CTagHelper::CTagHelper::Tag(s)
    * @see    self::JavascriptPath
    */
    static public function JavascriptIncludeTag()
    {
        $sources = func_get_args();
        $sourceOptions = (func_num_args() > 1 && is_array($sources[func_num_args() - 1])) ? array_pop($sources) : array();

        $html = '';
        foreach ($sources as $source)
        {
            $absolute = false;
            if (isset($sourceOptions['absolute']))
            {
                unset($sourceOptions['absolute']);
                $absolute = true;
            }

            $condition = null;
            if (isset($sourceOptions['condition']))
            {
                $condition = $sourceOptions['condition'];
                unset($sourceOptions['condition']);
            }

            if (!isset($sourceOptions['raw_name']))
            {
                $source = self::JavascriptPath($source, $absolute);
            }
            else
            {
                unset($sourceOptions['raw_name']);
            }

            $options = array_merge(array('type' => 'text/javascript', 
                'src' => $source), $sourceOptions);
            $tag = CTagHelper::ContentTag('script', '', $options);

            if (!is_null($condition))
            {
              $tag = CTagHelper::CommentAsConditional($condition, $tag);
            }

            $html .= $tag."\n";
        }

        return $html;
    }

    /**
    * Returns the path to a stylesheet asset.
    *
    * <b>Example:</b>
    * <code>
    *  echo self::StylesheetPath('style');
    *    => /css/style.css
    * </code>
    *
    * <b>Note:</b> The asset name can be supplied as a...
    * - full path, like "/my_css/style.css"
    * - file name, like "style.css", that gets expanded to "/css/style.css"
    * - file name without extension, like "style", that gets expanded to "/css/style.css"
    *
    * @param string $source   asset name
    * @param bool   $absolute return absolute path ?
    *
    * @return string file path to the stylesheet file
    * @see    self::StylesheetTag
    */
    static public function StylesheetPath($source, $absolute = false)
    {
        return self::_ComputePublicPath($source, 'css', 'css', $absolute);
    }

    /**
    * Returns a css <link> CTagHelper::CTagHelper::Tag per source given as argument,
    * to be included in the <head> section of a HTML document.
    *
    * <b>Options:</b>
    * - rel - defaults to 'stylesheet'
    * - type - defaults to 'text/css'
    * - media - defaults to 'screen'
    *
    * <b>Examples:</b>
    * <code>
    *  echo self::StylesheetTag('style');
    *    => <link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
    *  echo self::StylesheetTag('style', array('media' => 'all'));
    *    => <link href="/stylesheets/style.css" media="all" rel="stylesheet" type="text/css" />
    *  echo self::StylesheetTag('style', array('raw_name' => true));
    *    => <link href="style" media="all" rel="stylesheet" type="text/css" />
    *  echo self::StylesheetTag('random.styles', '/css/stylish');
    *    => <link href="/stylesheets/random.styles" media="screen" rel="stylesheet" type="text/css" />
    *       <link href="/css/stylish.css" media="screen" rel="stylesheet" type="text/css" />
    * </code>
    *
    * @param string asset names
    * @param array  additional HTML compliant <link> CTagHelper::CTagHelper::Tag parameters
    *
    * @return string XHTML compliant <link> CTagHelper::CTagHelper::Tag(s)
    * @see    self::StylesheetPath
    */
    static public function StylesheetTag()
    {
        $sources = func_get_args();
        $sourceOptions = (func_num_args() > 1 && is_array($sources[func_num_args() - 1])) ? 
            array_pop($sources) : array();

        $html = '';
        foreach ($sources as $source)
        {
            $absolute = false;
            if (isset($sourceOptions['absolute']))
            {
                unset($sourceOptions['absolute']);
                $absolute = true;
            }

            $condition = null;
            if (isset($sourceOptions['condition']))
            {
                $condition = $sourceOptions['condition'];
                unset($sourceOptions['condition']);
            }

            if (!isset($sourceOptions['raw_name']))
            {
                $source = self::StylesheetPath($source, $absolute);
            }
            else
            {
                unset($sourceOptions['raw_name']);
            }

            $options = array_merge(array('rel' => 'stylesheet', 
                'type' => 'text/css', 'media' => 'screen', 'href' => $source), 
                $sourceOptions);
            $tag = CTagHelper::Tag('link', $options);

            if (!is_null($condition))
            {
                $tag = CTagHelper::CommentAsConditional($condition, $tag);
            }

            $html .= $tag."\n";
        }

        return $html;
    }

    /**
    * Returns the path to an image asset.
    *
    * <b>Example:</b>
    * <code>
    *  echo self::ImagePath('foobar');
    *    => /images/foobar.png
    * </code>
    *
    * <b>Note:</b> The asset name can be supplied as a...
    * - full path, like "/my_images/image.gif"
    * - file name, like "rss.gif", that gets expanded to "/images/rss.gif"
    * - file name without extension, like "logo", that gets expanded to "/images/logo.png"
    *
    * @param string $source   asset name
    * @param bool   $absolute return absolute path ?
    *
    * @return string file path to the image file
    * @see    self::ImageTag
    */
    static public function ImagePath($source, $absolute = false)
    {
        return self::_ComputePublicPath($source, 'images', 'png', $absolute);
    }

    /**
    * Returns an <img> image CTagHelper::CTagHelper::Tag for the asset given as argument.
    *
    * <b>Options:</b>
    * - 'absolute' - to output absolute file paths, useful for embedded images in emails
    * - 'alt'  - defaults to the file name part of the asset (capitalized and without the extension)
    * - 'size' - Supplied as "XxY", so "30x45" becomes width="30" and height="45"
    *
    * <b>Examples:</b>
    * <code>
    *  echo self::ImageTag('foobar');
    *    => <img src="images/foobar.png" alt="Foobar" />
    *  echo self::ImageTag('/my_images/image.gif', array('alt' => 'Alternative text', 'size' => '100x200'));
    *    => <img src="/my_images/image.gif" alt="Alternative text" width="100" height="200" />
    * </code>
    *
    * @param string $source  image asset name
    * @param array  $options additional HTML compliant <img> CTagHelper::CTagHelper::Tag parameters
    *
    * @return string XHTML compliant <img> CTagHelper::CTagHelper::Tag
    * @see    self::ImagePath
    */
    static public function ImageTag($source, $options = array())
    {
        if (!$source)
        {
            return '';
        }

        $options = CtagHelper::_ParseAttributes($options);

        $absolute = false;
        if (isset($options['absolute']))
        {
            unset($options['absolute']);
            $absolute = true;
        }

        if (!isset($options['raw_name']))
        {
            $options['src'] = self::ImagePath($source, $absolute);
        }
        else
        {
            $options['src'] = $source;
            unset($options['raw_name']);
        }

        if (isset($options['alt_title']))
        {
            // set as alt and title but do not overwrite explicitly set
            if (!isset($options['alt']))
            {
                $options['alt'] = $options['alt_title'];
            }
            if (!isset($options['title']))
            {
                $options['title'] = $options['alt_title'];
            }
            unset($options['alt_title']);
        }

        if (!isset($options['alt']))
        {
            $path_pos = strrpos($source, '/');
            $dot_pos = strrpos($source, '.');
            $begin = $path_pos ? $path_pos + 1 : 0;
            $nb_str = ($dot_pos ? $dot_pos : strlen($source)) - $begin;
            $options['alt'] = ucfirst(substr($source, $begin, $nb_str));
        }

        if (isset($options['size']))
        {
            list($options['width'], $options['height']) = explode('x', $options['size'], 2);
            unset($options['size']);
        }

        return CTagHelper::Tag('img', $options);
    }

    static public function _ComputePublicPath($source, $dir, $ext, $absolute = false)
    {
        if (strpos($source, '://'))
        {
            return $source;
        }

        $request = CRequest::Get();
        $sf_relative_url_root = $request->GetRelativeUrlRoot();
        if (0 !== strpos($source, '/'))
        {
        $source = $sf_relative_url_root.'/'.$dir.'/'.$source;
        }

        $query_string = '';
        if (false !== $pos = strpos($source, '?'))
        {
        $query_string = substr($source, $pos);
        $source = substr($source, 0, $pos);
        }

        if (false === strpos(basename($source), '.'))
        {
        $source .= '.'.$ext;
        }

        if ($sf_relative_url_root && 0 !== strpos($source, $sf_relative_url_root))
        {
        $source = $sf_relative_url_root.$source;
        }

        if ($absolute)
        {
        $source = 'http'.($request->IsSecure() ? 's' : '').'://'.$request->GetHost().$source;
        }

        return $source.$query_string;
    }

    /**
    * Prints a set of <meta> tags according to the response attributes,
    * to be included in the <head> section of a HTML document.
    *
    * <b>Examples:</b>
    * <code>
    *  self::IncludeMetas();
    *    => <meta name="title" content="symfony - open-source PHP5 web framework" />
    *       <meta name="robots" content="index, follow" />
    *       <meta name="description" content="symfony - open-source PHP5 web framework" />
    *       <meta name="keywords" content="symfony, project, framework, php, php5, open-source, mit, symphony" />
    *       <meta name="language" content="en" /><link href="/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />
    * </code>
    *
    * <b>Note:</b> Modify the view.yml or use sfWebResponse::addMeta() to change, add or remove metas.
    *
    * @return string XHTML compliant <meta> CTagHelper::CTagHelper::Tag(s)
    * @see    self::IncludeHttpMetas
    * @see    sfWebResponse::addMeta()
    */
    static public function IncludeMetas()
    {
        foreach (CResponse::Get()->GetMetas() as $name => $content)
        {
            echo CTagHelper::Tag('meta', 
                array('name' => $name, '
                    content' => is_null($i18n) ? $content : $i18n->__($content)
                )
            )."\n";
        }
    }

    /**
    * Returns a set of <meta http-equiv> tags according to the response attributes,
    * to be included in the <head> section of a HTML document.
    *
    * <b>Examples:</b>
    * <code>
    *  self::IncludeHttpMetas();
    *    => <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    * </code>
    *
    * <b>Note:</b> Modify the view.yml or use sfWebResponse::addHttpMeta() to change, add or remove HTTP metas.
    *
    * @return string XHTML compliant <meta> CTagHelper::CTagHelper::Tag(s)
    * @see    self::IncludeMetas
    * @see    sfWebResponse::addHttpMeta()
    */
    static public function IncludeHttpMetas()
    {
        foreach (CResponse::Get()->GetHttpMetas() as $httpequiv => $value)
        {
            echo CTagHelper::Tag('meta', 
                array('http-equiv' => $httpequiv, 'content' => $value))."\n";
        }
    }

    /**
    * Returns the title of the current page according to the response attributes,
    * to be included in the <title> section of a HTML document.
    *
    * <b>Note:</b> Modify the sfResponse object or the view.yml to modify the title of a page.
    *
    * @return string page title
    */
    static public function IncludeTitle()
    {
        $title = CResponse::Get()->GetTitle();

        echo CTagHelper::ContentTag('title', $title)."\n";
    }

    /**
    * Returns <script> tags for all javascripts configured in view.yml or added to the response object.
    *
    * You can use this helper to decide the location of javascripts in pages.
    * By default, if you don't call this helper, symfony will automatically include javascripts before </head>.
    * Calling this helper disables this behavior.
    *
    * @return string <script> tags
    */
    static public function GetJavascripts()
    {
        $html = '';
        foreach (CResponse::Get()->GetJavascripts() as $file => $options)
        {
            $html .= self::JavascriptIncludeTag($file, $options);
        }

        return $html;
    }

    /**
    * Prints <script> tags for all javascripts configured in view.yml or added to the response object.
    *
    * @see self::GetJavascripts()
    */
    static public function IncludeJavascripts()
    {
        echo self::GetJavascripts();
    }

    /**
    * Returns <link> tags for all stylesheets configured in view.yml or added to the response object.
    *
    * You can use this helper to decide the location of stylesheets in pages.
    * By default, if you don't call this helper, symfony will automatically include stylesheets before </head>.
    * Calling this helper disables this behavior.
    *
    * @return string <link> tags
    */
    static public function GetStylesheets()
    {
        $html = '';
        foreach (CResponse::Get()->GetStylesheets() as $file => $options)
        {
            $html .= self::StylesheetTag($file, $options);
        }

        return $html;
    }

    /**
    * Prints <link> tags for all stylesheets configured in view.yml or added to the response object.
    *
    * @see get_stylesheets()
    */
    static public function IncludeStylesheets()
    {
        echo self::GetStylesheets();
    }
}

class HAsset extends CAssetHelper{} 
?>
